﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Drawing;
using System.Text.RegularExpressions;

namespace BigPixels
{
	[Serializable]
	[XmlType(TypeName = "Pixel")]
	public class PixelValue
    {
        public PixelValue()
        {
            this.Value = Color.Empty;
        }

        public PixelValue(string hexValue)
        {
            this.Value = HexStringToColor(hexValue);
        }

        public PixelValue(Color value)
        {
            this.Value = value;
        }

        public bool IsValid
        {
            get { return this.Value != Color.Empty; }
        }

        [XmlIgnore]
        public Color Value
        {
            get;
            set;
        }

		[XmlAttribute("Value")]
		public string HexValue
        {
            get
            {
                return ColourToHexString(this.Value);
            }

            set
            {
                this.Value = HexStringToColor(value);
            }
        }
        
        public static string ColourToHexString(Color color)
        {
            if (color == Color.Empty)
                return string.Empty;

            char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

            byte[] bytes = new byte[3];
            bytes[0] = color.R;
            bytes[1] = color.G;
            bytes[2] = color.B;

            char[] chars = new char[bytes.Length * 2];

            for (int i = 0; i < bytes.Length; i++)
            {
                int b = bytes[i];
                chars[i * 2] = hexDigits[b >> 4];
                chars[i * 2 + 1] = hexDigits[b & 0xF];
            }

            return new string(chars);
        }

        private static Color HexStringToColor(string hexColor)
        {
            if (string.IsNullOrEmpty(hexColor))
                return Color.Empty;

            string hc = ExtractHexDigits(hexColor);
            if (hc.Length != 6)
            {
                // you can choose whether to throw an exception
                //throw new ArgumentException("hexColor is not exactly 6 digits.");
                return Color.Empty;
            }

            string r = hc.Substring(0, 2);
            string g = hc.Substring(2, 2);
            string b = hc.Substring(4, 2);

            Color color = Color.Empty;
            try
            {
                int ri = Int32.Parse(r, System.Globalization.NumberStyles.HexNumber);
                int gi = Int32.Parse(g, System.Globalization.NumberStyles.HexNumber);
                int bi = Int32.Parse(b, System.Globalization.NumberStyles.HexNumber);
                color = Color.FromArgb(ri, gi, bi);
            }
            catch
            {
                // you can choose whether to throw an exception
                //throw new ArgumentException("Conversion failed.");
                return Color.Empty;
            }

            return color;
        }
        /// <summary>
        /// Extract only the hex digits from a string.
        /// </summary>
        private static string ExtractHexDigits(string input)
        {
            // remove any characters that are not digits (like #)
            Regex isHexDigit = new Regex("[abcdefABCDEF\\d]+", RegexOptions.Compiled);
            string newnum = "";
            foreach (char c in input)
            {
                if (isHexDigit.IsMatch(c.ToString()))
                    newnum += c.ToString();
            }

            return newnum;
        }
    }
}
